
<!DOCTYPE html>
<html lang="en" class="loading">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>07_继承 - fubaisen</title>
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <meta name="google" content="notranslate" />
    <meta name="keywords" content="Fechin,"> 
    <meta name="description" content="继承目标
单继承
多继承

面向对象三大特性

封装 根据 职责 将 属性 和 方法 封装 到一个抽象的 类 中
继承 实现代码的重用，相同的代码不需要重复的编写
多态 不同的对象调用相同的方法，产,"> 
    <meta name="author" content="John Doe"> 
    <link rel="alternative" href="atom.xml" title="fubaisen" type="application/atom+xml"> 
    <link rel="icon" href="/img/favicon.png"> 
    
    
    
    <meta name="twitter:card" content="summary"/>
    <meta name="twitter:title" content="07_继承 - fubaisen"/>
    <meta name="twitter:description" content="继承目标
单继承
多继承

面向对象三大特性

封装 根据 职责 将 属性 和 方法 封装 到一个抽象的 类 中
继承 实现代码的重用，相同的代码不需要重复的编写
多态 不同的对象调用相同的方法，产,"/>
    
    
    
    
    <meta property="og:site_name" content="fubaisen"/>
    <meta property="og:type" content="object"/>
    <meta property="og:title" content="07_继承 - fubaisen"/>
    <meta property="og:description" content="继承目标
单继承
多继承

面向对象三大特性

封装 根据 职责 将 属性 和 方法 封装 到一个抽象的 类 中
继承 实现代码的重用，相同的代码不需要重复的编写
多态 不同的对象调用相同的方法，产,"/>
    
<link rel="stylesheet" href="/css/diaspora.css">

    <script>window.searchDbPath = "/search.xml";</script>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Source+Code+Pro&display=swap" rel="stylesheet">
<meta name="generator" content="Hexo 6.3.0"></head>

<body class="loading">
    <span id="config-title" style="display:none">fubaisen</span>
    <div id="loader"></div>
    <div id="single">
    <div id="top" style="display: block;">
    <div class="bar" style="width: 0;"></div>
    <a class="iconfont icon-home image-icon" href="javascript:;" data-url="http://fubaisen.github.io"></a>
    <div title="播放/暂停" class="iconfont icon-play"></div>
    <h3 class="subtitle">07_继承</h3>
    <div class="social">
        <div>
            <div class="share">
                <a title="获取二维码" class="iconfont icon-scan" href="javascript:;"></a>
            </div>
            <div id="qr"></div>
        </div>
    </div>
    <div class="scrollbar"></div>
</div>

    <div class="section">
        <div class="article">
    <div class='main'>
        <h1 class="title">07_继承</h1>
        <div class="stuff">
            <span>三月 23, 2022</span>
            
  <ul class="post-tags-list" itemprop="keywords"><li class="post-tags-list-item"><a class="post-tags-list-link" href="/tags/python%E5%AD%A6%E4%B9%A0/" rel="tag">python学习</a></li></ul>


        </div>
        <div class="content markdown">
            <h1 id="继承"><a href="#继承" class="headerlink" title="继承"></a>继承</h1><h2 id="目标"><a href="#目标" class="headerlink" title="目标"></a>目标</h2><ul>
<li>单继承</li>
<li>多继承</li>
</ul>
<p><strong>面向对象三大特性</strong></p>
<ol>
<li><strong>封装</strong> 根据 <strong>职责</strong> 将 <strong>属性</strong> 和 <strong>方法</strong> <strong>封装</strong> 到一个抽象的 <strong>类</strong> 中</li>
<li><strong>继承</strong> <strong>实现代码的重用</strong>，相同的代码不需要重复的编写</li>
<li><strong>多态</strong> 不同的对象调用相同的方法，产生不同的执行结果，<strong>增加代码的灵活度</strong></li>
</ol>
<h2 id="01-单继承"><a href="#01-单继承" class="headerlink" title="01. 单继承"></a>01. 单继承</h2><h3 id="1-1-继承的概念、语法和特点"><a href="#1-1-继承的概念、语法和特点" class="headerlink" title="1.1 继承的概念、语法和特点"></a>1.1 继承的概念、语法和特点</h3><p><strong>继承的概念</strong>：<strong>子类</strong> 拥有 <strong>父类</strong> 的所有 <strong>方法</strong> 和 <strong>属性</strong></p>
<p><img src="https://s2.loli.net/2022/03/20/w29N81CdsuxOPqI.png" alt="011_继承对比图示"></p>
<h4 id="1-继承的语法"><a href="#1-继承的语法" class="headerlink" title="1) 继承的语法"></a>1) 继承的语法</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">类名</span>(<span class="title class_ inherited__">父类名</span>):</span><br><span class="line"></span><br><span class="line">    <span class="keyword">pass</span></span><br></pre></td></tr></table></figure>

<ul>
<li><strong>子类</strong> 继承自 <strong>父类</strong>，可以直接 <strong>享受</strong> 父类中已经封装好的方法，不需要再次开发</li>
<li><strong>子类</strong> 中应该根据 <strong>职责</strong>，封装 <strong>子类特有的</strong> <strong>属性和方法</strong></li>
</ul>
<h4 id="2-专业术语"><a href="#2-专业术语" class="headerlink" title="2) 专业术语"></a>2) 专业术语</h4><ul>
<li><code>Dog</code> 类是 <code>Animal</code> 类的<strong>子类</strong>，<code>Animal</code> 类是 <code>Dog</code> 类的<strong>父类</strong>，<code>Dog</code> 类从 <code>Animal</code> 类<strong>继承</strong></li>
<li><code>Dog</code> 类是 <code>Animal</code> 类的<strong>派生类</strong>，<code>Animal</code> 类是 <code>Dog</code> 类的<strong>基类</strong>，<code>Dog</code> 类从 <code>Animal</code> 类<strong>派生</strong></li>
</ul>
<h4 id="3-继承的传递性"><a href="#3-继承的传递性" class="headerlink" title="3) 继承的传递性"></a>3) 继承的传递性</h4><ul>
<li><code>C</code> 类从 <code>B</code> 类继承，<code>B</code> 类又从 <code>A</code> 类继承</li>
<li>那么 <code>C</code> 类就具有 <code>B</code> 类和 <code>A</code> 类的所有属性和方法</li>
</ul>
<p><strong>子类</strong> 拥有 <strong>父类</strong> 以及 <strong>父类的父类</strong> 中封装的所有 <strong>属性</strong> 和 <strong>方法</strong></p>
<p><strong>提问</strong></p>
<p><strong>哮天犬</strong> 能够调用 <code>Cat</code> 类中定义的 <code>catch</code> 方法吗？</p>
<p><strong>答案</strong></p>
<p><strong>不能</strong>，因为 <strong>哮天犬</strong> 和 <code>Cat</code> 之间没有 <strong>继承</strong> 关系</p>
<h3 id="1-2-方法的重写"><a href="#1-2-方法的重写" class="headerlink" title="1.2 方法的重写"></a>1.2 方法的重写</h3><ul>
<li><strong>子类</strong> 拥有 <strong>父类</strong> 的所有 <strong>方法</strong> 和 <strong>属性</strong></li>
<li><strong>子类</strong> 继承自 <strong>父类</strong>，可以直接 <strong>享受</strong> 父类中已经封装好的方法，不需要再次开发</li>
</ul>
<p><strong>应用场景</strong></p>
<ul>
<li>当 <strong>父类</strong> 的方法实现不能满足子类需求时，可以对方法进行 <strong>重写(override)</strong></li>
</ul>
<p><img src="https://s2.loli.net/2022/03/20/EOzN2ZxCDJa9lLB.png" alt="012_继承方法的重写"></p>
<p><strong>重写</strong> 父类方法有两种情况：</p>
<ol>
<li><strong>覆盖</strong> 父类的方法</li>
<li>对父类方法进行 <strong>扩展</strong></li>
</ol>
<h4 id="1-覆盖父类的方法"><a href="#1-覆盖父类的方法" class="headerlink" title="1) 覆盖父类的方法"></a>1) 覆盖父类的方法</h4><ul>
<li>如果在开发中，<strong>父类的方法实现</strong> 和 <strong>子类的方法实现</strong>，<strong>完全不同</strong></li>
<li>就可以使用 <strong>覆盖</strong> 的方式，<strong>在子类中</strong> <strong>重新编写</strong> 父类的方法实现</li>
</ul>
<blockquote>
<p>具体的实现方式，就相当于在 <strong>子类中</strong> 定义了一个 <strong>和父类同名的方法并且实现</strong></p>
</blockquote>
<p>重写之后，在运行时，<strong>只会调用</strong> 子类中重写的方法，而不再会调用 <strong>父类封装的方法</strong></p>
<h4 id="2-对父类方法进行-扩展"><a href="#2-对父类方法进行-扩展" class="headerlink" title="2) 对父类方法进行 扩展"></a>2) 对父类方法进行 <strong>扩展</strong></h4><ul>
<li>如果在开发中，子类的方法实现中包含父类的方法实现<ul>
<li><strong>父类原本封装的方法实现</strong> 是 <strong>子类方法的一部分</strong></li>
</ul>
</li>
<li>就可以使用扩展的方式<ol>
<li><strong>在子类中</strong> <strong>重写</strong> 父类的方法</li>
<li>在需要的位置使用 <code>super().父类方法</code> 来调用父类方法的执行</li>
<li>代码其他的位置针对子类的需求，编写 <strong>子类特有的代码实现</strong></li>
</ol>
</li>
</ul>
<h5 id="关于-super"><a href="#关于-super" class="headerlink" title="关于 super"></a>关于 <code>super</code></h5><ul>
<li>在 <code>Python</code> 中 <code>super</code> 是一个 <strong>特殊的类</strong></li>
<li><code>super()</code> 就是使用 <code>super</code> 类创建出来的对象</li>
<li><strong>最常</strong> 使用的场景就是在 <strong>重写父类方法时</strong>，调用 <strong>在父类中封装的方法实现</strong></li>
</ul>
<h5 id="调用父类方法的另外一种方式（知道）"><a href="#调用父类方法的另外一种方式（知道）" class="headerlink" title="调用父类方法的另外一种方式（知道）"></a>调用父类方法的另外一种方式（知道）</h5><blockquote>
<p>在 <code>Python 2.x</code> 时，如果需要调用父类的方法，还可以使用以下方式：</p>
</blockquote>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">父类名.方法(self)</span><br></pre></td></tr></table></figure>

<ul>
<li>这种方式，目前在 <code>Python 3.x</code> 还支持这种方式</li>
<li>这种方法 <strong>不推荐使用</strong>，因为一旦 <strong>父类发生变化</strong>，方法调用位置的 <strong>类名</strong> 同样需要修改</li>
</ul>
<p><strong>提示</strong></p>
<ul>
<li>在开发时，<code>父类名</code> 和 <code>super()</code> 两种方式不要混用</li>
<li>如果使用 <strong>当前子类名</strong> 调用方法，会形成递归调用，<strong>出现死循环</strong></li>
</ul>
<h3 id="1-3-父类的-私有属性-和-私有方法"><a href="#1-3-父类的-私有属性-和-私有方法" class="headerlink" title="1.3 父类的 私有属性 和 私有方法"></a>1.3 父类的 私有属性 和 私有方法</h3><ol>
<li><strong>子类对象</strong> <strong>不能</strong> 在自己的方法内部，<strong>直接</strong> 访问 父类的 <strong>私有属性</strong> 或 <strong>私有方法</strong></li>
<li><strong>子类对象</strong> 可以通过 <strong>父类</strong> 的 <strong>公有方法</strong> <strong>间接</strong> 访问到 <strong>私有属性</strong> 或 <strong>私有方法</strong></li>
</ol>
<blockquote>
<ul>
<li><strong>私有属性、方法</strong> 是对象的隐私，不对外公开，<strong>外界</strong> 以及 <strong>子类</strong> 都不能直接访问</li>
<li><strong>私有属性、方法</strong> 通常用于做一些内部的事情</li>
</ul>
</blockquote>
<p><strong>示例</strong></p>
<p><img src="https://s2.loli.net/2022/03/20/j2Hx9N7g6SEek8q.png" alt="013_父类的私有属性和私有方法"></p>
<ul>
<li><code>B</code> 的对象不能直接访问 <code>__num2</code> 属性</li>
<li><code>B</code> 的对象不能在 <code>demo</code> 方法内访问 <code>__num2</code> 属性</li>
<li><code>B</code> 的对象可以在 <code>demo</code> 方法内，调用父类的 <code>test</code> 方法</li>
<li>父类的 <code>test</code> 方法内部，能够访问 <code>__num2</code> 属性和 <code>__test</code> 方法</li>
<li><code>B</code>的对象不可以   以直接直接调用父类<code>text</code>方法，进而直接访问</li>
</ul>
<h2 id="02-多继承"><a href="#02-多继承" class="headerlink" title="02. 多继承"></a>02. 多继承</h2><p><strong>概念</strong></p>
<ul>
<li><strong>子类</strong> 可以拥有 <strong>多个父类</strong>，并且具有 <strong>所有父类</strong> 的 <strong>属性</strong> 和 <strong>方法</strong></li>
<li>例如：<strong>孩子</strong> 会继承自己 <strong>父亲</strong> 和 <strong>母亲</strong> 的 <strong>特性</strong></li>
</ul>
<p><img src="https://s2.loli.net/2022/03/20/xzuibnWfoL6IUkj.png" alt="014_多继承"><strong>语法</strong></p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">子类名</span>(父类名<span class="number">1</span>, 父类名<span class="number">2.</span>..)</span><br><span class="line">    <span class="keyword">pass</span></span><br></pre></td></tr></table></figure>

<h3 id="2-1-多继承的使用注意事项"><a href="#2-1-多继承的使用注意事项" class="headerlink" title="2.1 多继承的使用注意事项"></a>2.1 多继承的使用注意事项</h3><p><strong>问题的提出</strong></p>
<ul>
<li>如果 <strong>不同的父类</strong> 中存在 <strong>同名的方法</strong>，<strong>子类对象</strong> 在调用方法时，会调用 <strong>哪一个父类中</strong>的方法呢？</li>
</ul>
<blockquote>
<p>提示：<strong>开发时，应该尽量避免这种容易产生混淆的情况！</strong> —— 如果 <strong>父类之间</strong> 存在 <strong>同名的属性或者方法</strong>，应该 <strong>尽量避免</strong> 使用多继承</p>
</blockquote>
<p><img src="https://s2.loli.net/2022/03/20/MkCwRrghGNtfASL.png" alt="015_多继承II"></p>
<h4 id="Python-中的-MRO-——-方法搜索顺序（知道）"><a href="#Python-中的-MRO-——-方法搜索顺序（知道）" class="headerlink" title="Python 中的 MRO —— 方法搜索顺序（知道）"></a>Python 中的 MRO —— 方法搜索顺序（知道）</h4><ul>
<li><code>Python</code> 中针对 <strong>类</strong> 提供了一个 <strong>内置属性</strong> <code>__mro__</code> 可以查看 <strong>方法</strong> 搜索顺序</li>
<li>MRO 是 <code>method resolution order</code>，主要用于 <strong>在多继承时判断 方法、属性 的调用 路径</strong></li>
</ul>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">print</span>(C.__mro__)</span><br></pre></td></tr></table></figure>

<p><strong>输出结果</strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">(&lt;class &#x27;__main__.C&#x27;&gt;, &lt;class &#x27;__main__.A&#x27;&gt;, &lt;class &#x27;__main__.B&#x27;&gt;, &lt;class &#x27;object&#x27;&gt;)</span><br></pre></td></tr></table></figure>

<ul>
<li>在搜索方法时，是按照 <code>__mro__</code> 的输出结果 <strong>从左至右</strong> 的顺序查找的</li>
<li>如果在当前类中 <strong>找到方法，就直接执行，不再搜索</strong></li>
<li>如果 <strong>没有找到，就查找下一个类</strong> 中是否有对应的方法，<strong>如果找到，就直接执行，不再搜索</strong></li>
<li>如果找到最后一个类，还没有找到方法，程序报错</li>
</ul>
<h3 id="2-2-新式类与旧式（经典）类"><a href="#2-2-新式类与旧式（经典）类" class="headerlink" title="2.2 新式类与旧式（经典）类"></a>2.2 新式类与旧式（经典）类</h3><blockquote>
<p><code>object</code> 是 <code>Python</code> 为所有对象提供的 <strong>基类</strong>，提供有一些内置的属性和方法，可以使用 <code>dir</code> 函数查看</p>
</blockquote>
<ul>
<li><strong>新式类</strong>：以 <code>object</code> 为基类的类，<strong>推荐使用</strong></li>
<li><strong>经典类</strong>：不以 <code>object</code> 为基类的类，<strong>不推荐使用</strong></li>
<li>在 <code>Python 3.x</code> 中定义类时，如果没有指定父类，会 <strong>默认使用</strong> <code>object</code> 作为该类的 <strong>基类</strong> —— <code>Python 3.x</code> 中定义的类都是 <strong>新式类</strong></li>
<li>在 <code>Python 2.x</code> 中定义类时，如果没有指定父类，则不会以 </li>
<li><code>object</code> 作为 <strong>基类</strong></li>
</ul>
<blockquote>
<p><strong>新式类</strong> 和 <strong>经典类</strong> 在多继承时 —— <strong>会影响到方法的搜索顺序</strong></p>
</blockquote>
<p>为了保证编写的代码能够同时在 <code>Python 2.x</code> 和 <code>Python 3.x</code> 运行！<br>今后在定义类时，<strong>如果没有父类，建议统一继承自 <code>object</code></strong></p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">类名</span>(<span class="title class_ inherited__">object</span>):</span><br><span class="line">    <span class="keyword">pass</span></span><br></pre></td></tr></table></figure>
            <!--[if lt IE 9]><script>document.createElement('audio');</script><![endif]-->
            <audio id="audio" loop="1" preload="auto" controls="controls" data-autoplay="false">
                <source type="audio/mpeg" src="">
            </audio>
            
                <ul id="audio-list" style="display:none">
                    
                        
                            <li title="0" data-url="http://link.hhtjim.com/163/425570952.mp3"></li>
                        
                    
                        
                            <li title="1" data-url="http://link.hhtjim.com/163/425570952.mp3"></li>
                        
                    
                </ul>
            
        </div>
        
        
    <div id="gitalk-container" class="comment link"
		data-enable="false"
        data-ae="false"
        data-ci=""
        data-cs=""
        data-r=""
        data-o=""
        data-a=""
        data-d="false"
    >查看评论</div>


    </div>
    
</div>


    </div>
</div>
</body>


<script src="//lib.baomitu.com/jquery/1.8.3/jquery.min.js"></script>
<script src="/js/plugin.js"></script>
<script src="/js/typed.js"></script>
<script src="/js/diaspora.js"></script>


<link rel="stylesheet" href="/photoswipe/photoswipe.css">
<link rel="stylesheet" href="/photoswipe/default-skin/default-skin.css">


<script src="/photoswipe/photoswipe.min.js"></script>
<script src="/photoswipe/photoswipe-ui-default.min.js"></script>


<!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
    <!-- Background of PhotoSwipe. 
         It's a separate element as animating opacity is faster than rgba(). -->
    <div class="pswp__bg"></div>
    <!-- Slides wrapper with overflow:hidden. -->
    <div class="pswp__scroll-wrap">
        <!-- Container that holds slides. 
            PhotoSwipe keeps only 3 of them in the DOM to save memory.
            Don't modify these 3 pswp__item elements, data is added later on. -->
        <div class="pswp__container">
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
        </div>
        <!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
        <div class="pswp__ui pswp__ui--hidden">
            <div class="pswp__top-bar">
                <!--  Controls are self-explanatory. Order can be changed. -->
                <div class="pswp__counter"></div>
                <button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
                <button class="pswp__button pswp__button--share" title="Share"></button>
                <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
                <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
                <!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
                <!-- element will get class pswp__preloader--active when preloader is running -->
                <div class="pswp__preloader">
                    <div class="pswp__preloader__icn">
                      <div class="pswp__preloader__cut">
                        <div class="pswp__preloader__donut"></div>
                      </div>
                    </div>
                </div>
            </div>
            <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
                <div class="pswp__share-tooltip"></div> 
            </div>
            <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
            </button>
            <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
            </button>
            <div class="pswp__caption">
                <div class="pswp__caption__center"></div>
            </div>
        </div>
    </div>
</div>






</html>
